﻿using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace CueCorrector
{
    public class MessageLabel : Label
    {
        public bool Changed
        {
            get { return (bool) GetValue(ChangedProperty); }
            set { SetValue(ChangedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ChangedProperty =
            DependencyProperty.Register("Changed", typeof (bool), typeof (MessageLabel), new UIPropertyMetadata(false));

        public MessageLabel()
        {
            var openFile = new MenuItem {Header = "Открыть"};
            var openFileWithNotepad = new MenuItem {Header = "Открыть блокнотом"};
            var openFolder = new MenuItem {Header = "Открыть папку"};
            openFile.Click += OpenFile_Click;
            openFileWithNotepad.Click += OpenFileWithNotepad_Click;
            openFolder.Click += OpenFolder_Click;
            var cm = new ContextMenu();
            cm.Items.Add(openFile);
            cm.Items.Add(openFileWithNotepad);
            cm.Items.Add(openFolder);
            ContextMenu = cm;
        }

        void OpenFileWithNotepad_Click(object sender, RoutedEventArgs e)
        {
            OpenNotepad();
        }

        void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenDefault();
        }

        void OpenFolder_Click(object sender, RoutedEventArgs e)
        {
            OpenFolder();
        }

        public void OpenDefault()
        {
            System.Diagnostics.Process.Start(((TextBlock) Content).Text);
        }

        public void OpenNotepad()
        {
            System.Diagnostics.Process.Start("notepad.exe", ((TextBlock)Content).Text);
        }

        public void OpenFolder()
        {
            var folder = Path.GetDirectoryName(((TextBlock) Content).Text);
            if (folder != null)
            {
                System.Diagnostics.Process.Start(folder);
            }
        }
    }

    public partial class MainWindow
    {
        private const string LastPathFileName = "last.txt";

        private readonly BackgroundWorker _worker = new BackgroundWorker
            {
                WorkerSupportsCancellation = true,
                WorkerReportsProgress = true
            };

        private readonly CueProcessor _cueProcessor = new CueProcessor();
        private DoWorkEventArgs _args;

        private readonly System.Windows.Forms.FolderBrowserDialog _dialog =
            new System.Windows.Forms.FolderBrowserDialog
                {
                    ShowNewFolderButton = false,
                    RootFolder = Environment.SpecialFolder.MyComputer
                };

        public MainWindow()
        {
            InitializeComponent();
            LoadLastPath();
            _cueProcessor.FileProcessed += CueProcessor_FileProcessed;
            _cueProcessor.Error += CueProcessor_Error;
            _cueProcessor.CheckCancellation = () => _args.Cancel = _worker.CancellationPending;
            _cueProcessor.ReportProgress = percentage => _worker.ReportProgress(percentage);
            ProgressBarFilesProcessed.Maximum = 100;
            _worker.DoWork += delegate(object s, DoWorkEventArgs args)
                {
                    _args = args;
                    _cueProcessor.Process();
                };
            _worker.RunWorkerCompleted += delegate
                {
                    ButtonCorrect.IsEnabled = true;
                    ButtonCancel.IsEnabled = false;
                    CheckBoxSaveOldFiles.IsEnabled = true;
                    ListBoxMessages.Items.Add(new Label
                        {
                            Content =
                                new TextBlock
                                    {
                                        Text =
                                            (!_cueProcessor.Stopped ? "Готово" : "Прервано пользователем") +
                                            ". Преобразовано файлов: " + _cueProcessor.ChangedFilesCount,
                                        Foreground = !_cueProcessor.Stopped ? Brushes.ForestGreen : Brushes.Red
                                    }
                        });
                    Cursor = Cursors.Arrow;
                };
            _worker.ProgressChanged +=
                (s, args) =>
                Dispatcher.BeginInvoke((Action) delegate { ProgressBarFilesProcessed.Value = args.ProgressPercentage; });
        }

        private void CueProcessor_FileProcessed(object sender, FileProcessedEventArgs e)
        {
            Dispatcher.BeginInvoke((Action) (() => ListBoxMessages.Items.Add(new MessageLabel
                {
                    Changed = e.Changed,
                    Content =
                        new TextBlock {Text = e.FileName, Foreground = e.Changed ? Brushes.ForestGreen : Brushes.Black},
                    ToolTip = e.Changed ? "Скорректирован" : "Не изменён",
                    Visibility =
                        e.Changed
                            ? Visibility.Visible
                            : CheckBoxShowUnmodified.IsChecked == true ? Visibility.Visible : Visibility.Collapsed
                })));
        }

        private void CueProcessor_Error(object sender, ErrorEventArgs e)
        {
            Dispatcher.BeginInvoke(
                (Action)
                (() =>
                 ListBoxMessages.Items.Add(new Label
                     {
                         Content = new TextBlock {Text = e.Message, Foreground = Brushes.Red},
                         ToolTip = "Ошибка!"
                     })));
        }

        private void Button_Choose_Click(object sender, RoutedEventArgs e)
        {
            if (Directory.Exists(TextBoxFolderPath.Text))
            {
                _dialog.SelectedPath = TextBoxFolderPath.Text;
            }
            if (_dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                ButtonCorrect.IsEnabled = true;
                TextBoxFolderPath.Text = _dialog.SelectedPath;
                SaveLastPath();
            }
            Clear();
        }

        private void Button_Correct_Click(object sender, RoutedEventArgs e)
        {
            Clear();
            ButtonCorrect.IsEnabled = false;
            CheckBoxSaveOldFiles.IsEnabled = false;
            ButtonCancel.IsEnabled = true;
            Cursor = Cursors.Wait;
            _cueProcessor.FolderPath = TextBoxFolderPath.Text;
            _cueProcessor.SaveOldFiles = CheckBoxSaveOldFiles.IsChecked == true;
            _worker.RunWorkerAsync();
        }

        private void TextBoxFolderPath_TextChanged(object sender, TextChangedEventArgs e)
        {
            Clear();
            ButtonCorrect.IsEnabled = !string.IsNullOrEmpty(TextBoxFolderPath.Text);
            _worker.CancelAsync();
            SaveLastPath();
        }

        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
        {
            _worker.CancelAsync();
        }

        private void CheckBox_ShowUnmodified_Checked(object sender, RoutedEventArgs e)
        {
            foreach (var message in ListBoxMessages.Items.OfType<MessageLabel>())
            {
                message.Visibility = Visibility.Visible;
            }
        }

        private void CheckBox_ShowUnmodified_Unchecked(object sender, RoutedEventArgs e)
        {
            foreach (var message in ListBoxMessages.Items.OfType<MessageLabel>())
            {
                message.Visibility = !message.Changed ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        #region private

        private void Clear()
        {
            ListBoxMessages.Items.Clear();
            ProgressBarFilesProcessed.Value = 0;
        }

        private void SaveLastPath()
        {
            try
            {
                File.WriteAllText(LastPathFileName, TextBoxFolderPath.Text);
            }
            catch (Exception ex)
            {
            }
        }

        private void LoadLastPath()
        {
            if (File.Exists(LastPathFileName))
            {
                try
                {
                    TextBoxFolderPath.Text = File.ReadAllText(LastPathFileName);
                }
                catch (Exception ex)
                {
                }
            }
        }

        #endregion

        private void ListBoxMessagesItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var item = sender as ListBoxItem;
            if (item == null) return;
            var label = item.Content as MessageLabel;
            if (label != null)
            {
                label.OpenDefault();
            }
        }
    }
}
